package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.annotation.PromiseStyleMinVersion
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.Promise

////////////////////
// Permissions
////////////////////
/**
 * Use the `Browser.permissions` API to request declared optional permissions at run time rather than install time, so users understand why the permissions are needed and grant only those that are necessary.
 */
interface Permissions {
    // Checks if the extension has the specified permissions.
    // @return {callback.result} True if the extension has the specified permissions.
    // If an origin is specified as both an optional permission and a content script match pattern,
    // this will return false unless both permissions are granted.
    @PromiseStyleMinVersion(96)
    fun contains(
        permission: Permissions,
        callback: Value1Function<Boolean>? = null
    ): Promise<Boolean>

    // Gets the extension's current set of permissions.
    // @return {callback.permissions} The extension's active permissions.
    // Note that the origins property will contain granted origins from those specified in the
    // permissions and optional_permissions keys in the manifest and those associated with Content Scripts.
    @PromiseStyleMinVersion(96)
    fun getAll(
        callback: Value1Function<Permissions>? = null
    ): Promise<Permissions>

    // Removes access to the specified permissions.
    // If there are any problems removing the permissions, runtime.lastError will be set.
    // @return {callback.removed} True if the permissions were removed.
    @PromiseStyleMinVersion(96)
    fun remove(
        permission: Permissions,
        callback: Value1Function<Boolean>? = null
    ): Promise<Boolean>

    // Requests access to the specified permissions, displaying a prompt to the user if necessary.
    // These permissions must either be defined in the optional_permissions field of the manifest or be required permissions that were withheld by the user.
    // Paths on origin patterns will be ignored.
    // You can request subsets of optional origin permissions; for example,
    // if you specify *://*\/* in the optional_permissions section of the manifest,
    // you can request http://example.com/.
    // If there are any problems requesting the permissions, runtime.lastError will be set.
    // @return {callback.granted} True if the user granted the specified permissions.
    @PromiseStyleMinVersion(96)
    fun request(
        permission: Permissions,
        callback: Value1Function<Boolean>? = null
    ): Promise<Boolean>

    /**
     * Adds a host access request. Request will only be signaled to the user if extension can be granted access to the host in the request. Request will be reset on cross-origin navigation. When accepted, grants persistent access to the site’s top origin
     * @since Chrome 133
     */
    @ChromeMinVersion(133)
    @PromiseStyleMinVersion(96)
    fun addHostAccessRequest(
        request: AddHostAccessRequest,
        callback: VoidFunction? = null
    ): Promise<Void>

    /**
     * Removes a host access request, if existent.
     * @since Chrome 133
     */
    @ChromeMinVersion(133)
    @PromiseStyleMinVersion(96)
    fun removeHostAccessRequest(
        request: RemoveHostAccessRequest,
        callback: VoidFunction? = null
    ): Promise<Void>

    // Fired when the extension acquires new permissions.
    val onAdded: Events.Event<Value1Function<Permissions>>

    // Fired when access to permissions has been removed from the extension.
    val onRemoved: Events.Event<Value1Function<Permissions>>


    data class Permissions(
        // The list of host permissions,
        // including those specified in the optional_permissions or permissions keys in the manifest,
        // and those associated with Content Scripts.
        var origins: List<String>? = null,
        // List of named permissions (does not include hosts or origins).
        var permissions: List<String>? = null
    )

    data class AddHostAccessRequest(
        /** The id of a document where host access requests can be shown. Must be the top-level document within a tab. If provided, the request is shown on the tab of the specified document and is removed when the document navigates to a new origin. Adding a new request will override any existent request for `tabId`. This or `tabId` must be specified. */
        var documentId: String?,
        /** The URL pattern where host access requests can be shown. If provided, host access requests will only be shown on URLs that match this pattern. */
        var pattern: String?,
        /** The id of the tab where host access requests can be shown. If provided, the request is shown on the specified tab and is removed when the tab navigates to a new origin. Adding a new request will override an existent request for `documentId`. This or `documentId` must be specified. */
        var tabId: Number?
    )

    data class RemoveHostAccessRequest(
        /** The id of a document where host access request will be removed. Must be the top-level document within a tab. This or `tabId` must be specified. */
        var documentId: String?,
        /** The URL pattern where host access request will be removed. If provided, this must exactly match the pattern of an existing host access request. */
        var pattern: String?,
        /** The id of the tab where host access request will be removed. This or `documentId` must be specified. */
        var tabId: Number?
    )
}